package logic_car

import (
	"APT/internal/consts"
	"APT/internal/dao"
	"APT/internal/library/aladdinApi"
	"APT/internal/library/contexts"
	"APT/internal/library/hgorm"
	"APT/internal/library/hgorm/handler"
	hook2 "APT/internal/library/hgorm/hook"
	"APT/internal/model/entity"
	"APT/internal/model/input/input_basics"
	"APT/internal/model/input/input_car"
	"APT/internal/model/input/input_refund"
	"APT/internal/service"
	"APT/utility/rabbitmq"
	"context"
	"fmt"
	"github.com/gogf/gf/v2/container/gvar"
	"github.com/gogf/gf/v2/database/gdb"
	"github.com/gogf/gf/v2/errors/gerror"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/os/gtime"
	"github.com/gogf/gf/v2/text/gstr"
	"github.com/shopspring/decimal"
	"strconv"
	"strings"
	"time"
)

type sCarOrder struct{}

func NewCarOrder() *sCarOrder {
	return &sCarOrder{}
}

func init() {
	service.RegisterCarOrder(NewCarOrder())
}

func (s *sCarOrder) Model(ctx context.Context, option ...*handler.Option) *gdb.Model {
	return handler.Model(dao.CarOrder.Ctx(ctx), option...)
}

func (s *sCarOrder) List(ctx context.Context, in *input_car.CarOrderListInp) (list []*input_car.CarOrderListModel, totalCount int, err error) {
	mod := s.Model(ctx).WithAll()

	mod = mod.FieldsPrefix(dao.CarOrder.Table(), input_car.CarOrderListModel{})
	mod = mod.Fields(hgorm.JoinFields(ctx, input_car.CarOrderListModel{}, &dao.PmsMember, "pmsMember"))

	mod = mod.LeftJoinOnFields(dao.PmsMember.Table(), dao.CarOrder.Columns().MemberId, "=", dao.PmsMember.Columns().Id)

	if !g.IsEmpty(in.OrderSn) {
		mod = mod.WhereLike(dao.CarOrder.Columns().OrderSn, "%"+in.OrderSn+"%")
	}

	if !g.IsEmpty(in.ServiceType) {
		mod = mod.WhereLike(dao.CarOrder.Columns().ServiceType, in.ServiceType)
	}

	if !g.IsEmpty(in.OrderType) {
		mod = mod.WhereLike(dao.CarOrder.Columns().OrderType, in.OrderType)
	}

	if !g.IsEmpty(in.MemberSearch) {
		mod = mod.Where(mod.Builder().
			WhereLike(dao.PmsMember.Columns().Id, "%"+in.MemberSearch+"%").
			WhereOrLike(dao.PmsMember.Columns().MemberNo, "%"+in.MemberSearch+"%").
			WhereOrLike(dao.CarOrder.Columns().BookingName, "%"+in.MemberSearch+"%").
			WhereOrLike(dao.CarOrder.Columns().BookingMobile, "%"+in.MemberSearch+"%"))
	}

	if !g.IsEmpty(in.OrderStatus) && in.OrderStatus != "ALL" {
		mod = mod.Where(dao.CarOrder.Columns().OrderStatus, in.OrderStatus)
	}

	if len(in.BookStartTime) == 2 {
		mod = mod.WhereBetween(dao.CarOrder.Columns().BookStartTime, in.BookStartTime[0], in.BookStartTime[1])
	}

	mod = mod.Page(in.Page, in.PerPage)

	mod = mod.OrderDesc(dao.CarOrder.Columns().Id)

	if err = mod.ScanAndCount(&list, &totalCount, false); err != nil {
		err = gerror.Wrap(err, "获取预订单列表失败，请稍后重试！")
		return
	}
	return
}

func (s *sCarOrder) View(ctx context.Context, in *input_car.CarOrderViewInp) (res *input_car.CarOrderViewModel, err error) {
	if err = s.Model(ctx).Hook(hook2.PmsFindLanguageValueHook).WithAll().Where(dao.CarOrder.Columns().OrderSn, in.OrderSn).Scan(&res); err != nil {
		err = gerror.Wrap(err, "获取预订单信息，请稍后重试！")
		return
	}

	for _, v := range res.LogList {
		if v.OperateType == "SYSTEM" {
			v.OperateName = "系统"
		}
		if v.OperateType == "ADMIN" {
			var AdminMemberInfo *entity.AdminMember
			if err = dao.AdminMember.Ctx(ctx).Where(dao.AdminMember.Columns().Id, v.OperateId).Scan(&AdminMemberInfo); err != nil {
				return
			}
			v.OperateName = AdminMemberInfo.Username
		}
		if v.OperateType == "USER" {
			var PmsMemberInfo *entity.PmsMember
			if err = dao.PmsMember.Ctx(ctx).Where(dao.PmsMember.Columns().Id, v.OperateId).Scan(&PmsMemberInfo); err != nil {
				return
			}
			v.OperateName = PmsMemberInfo.FullName
		}

		if v.OperateType == "DRIVER" {
			var CarDriverInfo *entity.CarDriver
			if err = dao.CarDriver.Ctx(ctx).Where(dao.CarDriver.Columns().Id, v.OperateId).Scan(&CarDriverInfo); err != nil {
				return
			}
			v.OperateName = CarDriverInfo.Name
		}
	}

	return
}

func (s *sCarOrder) ConfirmAgree(ctx context.Context, in *input_car.CarOrderConfirmAgreeInp) (err error) {

	var models *entity.CarOrder
	var serviceModels *entity.CarService
	if err = s.Model(ctx).Where("id", in.Id).Scan(&models); err != nil {
		err = gerror.Wrap(err, consts.ErrorORM)
		return
	}

	if models == nil {
		err = gerror.New("订单信息不存在或已被删除")
		return
	}

	if models.OrderStatus != "WAIT_CONFIRM" {
		err = gerror.New("订单状态不正确")
		return
	}

	if models.OrderType == "CRS" {
		if err = dao.CarService.Ctx(ctx).Where("id", models.ServiceId).Scan(&serviceModels); err != nil {
			err = gerror.Wrap(err, consts.ErrorORM)
			return
		}
		timeout := gtime.New(models.BookStartTime).Add(time.Duration(serviceModels.MaxWaitTime) * time.Minute)
		nowTime := gtime.Now()

		if nowTime.After(timeout) {
			err = gerror.New("服务时间已过")
			return
		}
	} else {
		timeout := gtime.New(models.BookStartTime).EndOfDay()
		nowTime := gtime.Now()

		if nowTime.After(timeout) {
			err = gerror.New("服务时间已过")
			return
		}
	}

	return g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) (err error) {
		if _, err = s.Model(ctx).
			WherePri(in.Id).Data(input_car.CarOrderConfirmAgreeFields{
			OrderStatus: "WAIT_SERVE",
			ConfirmTime: gtime.Now(),
		}).Update(); err != nil {
			err = gerror.Wrap(err, "操作失败，请稍后重试！")
			return
		}

		// 订单日志
		if _, err = dao.CarOrderLog.Ctx(ctx).OmitEmptyData().Insert(&entity.CarOrderLog{
			OrderId:     in.Id,
			OrderStatus: "WAIT_SERVE",
			ActionWay:   "CONFIRMED",
			Remark:      "订单已确认",
			OperateType: "ADMIN",
			OperateId:   int(contexts.GetUserId(ctx)),
		}); err != nil {
			return err
		}

		// 判断是否自动调度
		var (
			DriverList         []*entity.CarDriver
			WorkingDriverIds   []string
			LastOrderDriverId  []gdb.Value
			CheckOrderList     []*entity.CarOrder
			CanOrderDriverList []*entity.CarDriver
			DriverInfo         *entity.CarDriver
		)
		if models.DispatchType == 2 {
			if err = dao.CarDriver.Ctx(ctx).Where(dao.CarDriver.Columns().Status, 1).Order("work_status asc").Scan(&DriverList); err != nil {
				return
			}

			StartTime := gtime.New(models.BookStartTime).Timestamp()
			if err = dao.CarOrder.Ctx(ctx).Where(dao.CarOrder.Columns().BookDate, models.BookDate).WhereNot(dao.CarOrder.Columns().Id, in.Id).WhereIn(dao.CarOrder.Columns().OrderStatus, g.Slice{"WAIT_SERVE", "SERVING"}).Where(dao.CarOrder.Columns().DispatchStatus, "DONE").Scan(&CheckOrderList); err != nil {
				return
			}
			for _, v := range CheckOrderList {
				OrderStartTime := gtime.New(v.BookStartTime).Timestamp()
				if gtime.New(v.BookEndTime).Timestamp() <= StartTime || OrderStartTime >= gtime.New(models.BookEndTime).Timestamp() {

				} else {
					driverIdString := gvar.New(v.DriverId).String()
					WorkingDriverIds = append(WorkingDriverIds, driverIdString)
				}
			}
			if !g.IsEmpty(DriverList) {
				for _, v := range DriverList {
					if v.WorkStatus != "REST" && !gstr.InArray(WorkingDriverIds, strconv.Itoa(v.Id)) {
						CanOrderDriverList = append(CanOrderDriverList, v)
					}
				}
			}

			if !g.IsEmpty(DriverList) && !g.IsEmpty(CanOrderDriverList) {
				if LastOrderDriverId, err = dao.CarOrder.Ctx(ctx).Fields(dao.CarOrder.Columns().DriverId).Where(dao.CarOrder.Columns().DispatchStatus, "DONE").Where(dao.CarOrder.Columns().PayStatus, "HAVE_PAID").Order("dispatch_time desc").Array(); err != nil {
					return
				}

				if len(LastOrderDriverId) > 0 {
					DriverInfo = CanOrderDriverList[0]

					for k, v := range CanOrderDriverList {
						if g.NewVar(LastOrderDriverId).Ints()[0] == v.Id {
							if k != len(CanOrderDriverList)-1 {
								DriverInfo = CanOrderDriverList[k+1]
								break
							}
						}
					}
				} else {
					// 没有指定过就第一个司机
					DriverInfo = CanOrderDriverList[0]
				}

				if _, err = s.Model(ctx).
					WherePri(in.Id).Data(input_car.CarOrderDispatchInp{
					DispatchStatus:     "DONE",
					DispatchTime:       gtime.Now(),
					DispatchOperatorId: 0,
					DispatchDesc:       fmt.Sprintf("系统自动派单给%s", DriverInfo.Nickname),
					DriverId:           int(DriverInfo.Id),
					CarId:              int(DriverInfo.CarId),
				}).OmitEmptyData().Update(); err != nil {
					err = gerror.Wrap(err, "操作失败，请稍后重试！")
					return
				}
				// 订单日志
				if _, err = dao.CarOrderLog.Ctx(ctx).OmitEmptyData().Insert(&entity.CarOrderLog{
					OrderId:     in.Id,
					OrderStatus: "WAIT_SERVE",
					ActionWay:   "DISPATCH",
					Remark:      "预约成功，司机已接单",
					OperateType: "SYSTEM",
				}); err != nil {
					return err
				}

				// 打印
				_ = service.BasicsPrinter().PrinterCarOrder(ctx, &input_basics.PrinterCarOrderInp{
					OrderId: in.Id,
				})

				// 更新司机统计
				if _, err = dao.CarDriver.Ctx(ctx).Where(dao.CarDriver.Columns().Id, DriverInfo.Id).Update(g.MapStrAny{
					dao.CarDriver.Columns().TotalOrderNum:    gdb.Raw("total_order_num+1"),
					dao.CarDriver.Columns().TotalOrderAmount: gdb.Raw(fmt.Sprintf("total_order_amount+%f", models.OrderAmount)),
					dao.CarDriver.Columns().PayOrderNum:      gdb.Raw("pay_order_num+1"),
					dao.CarDriver.Columns().PayOrderAmount:   gdb.Raw(fmt.Sprintf("pay_order_amount+%f", models.OrderAmount)),
				}); err != nil {
					err = gerror.Wrap(err, "更新服务信息失败，请稍后重试！")
					return
				}

				// 写入结算
				var (
					CarSettlement   *entity.CarSettlement
					SettlementRate  float64
					SettlementType  int
					SettlementCycle int
				)
				if err = dao.CarSettlement.Ctx(ctx).WherePri(DriverInfo.SettlementId).Scan(&CarSettlement); err != nil {
					return
				}
				if DriverInfo.SettlementType == 1 {
					// 跟随系统
					if !g.IsEmpty(CarSettlement) {
						SettlementRate = CarSettlement.Rate
					} else {
						SettlementRate = 0
					}
				} else {
					// 自定义
					SettlementRate = DriverInfo.SettlementRate
				}
				if !g.IsEmpty(CarSettlement) {
					SettlementType = CarSettlement.Type
					SettlementCycle = CarSettlement.Cycle
				} else {
					SettlementType = 1
					SettlementCycle = 1
				}
				if _, err = s.Model(ctx).
					WherePri(in.Id).Data(input_car.CarOrderSettlementInp{
					SettlementRate:  SettlementRate,
					SettlementType:  SettlementType,
					SettlementCycle: SettlementCycle,
				}).OmitEmptyData().Update(); err != nil {
					err = gerror.Wrap(err, "操作失败，请稍后重试！")
					return
				}
			}
		}
		return
	})

}

// ConfirmDisagree 确认失败，全额退款
func (s *sCarOrder) ConfirmDisagree(ctx context.Context, in *input_car.CarOrderConfirmDisagreeInp) (err error) {

	var models *entity.CarOrder
	if err = s.Model(ctx).Where("id", in.Id).Scan(&models); err != nil {
		err = gerror.Wrap(err, consts.ErrorORM)
		return
	}

	if models == nil {
		err = gerror.New("订单信息不存在或已被删除")
		return
	}

	if models.OrderStatus != "WAIT_CONFIRM" {
		err = gerror.New("订单状态不正确")
		return
	}

	if models.RefundStatus != "WAIT" {
		err = gerror.New("订单已退款")
		return
	}

	return g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) (err error) {

		// 改变订单确认状态
		if _, err = s.Model(ctx).TX(tx).
			WherePri(in.Id).Data(input_car.CarOrderConfirmDisagreeFields{
			BookingStatus:       "CANCEL",
			ConfirmRefuseReason: in.ConfirmRefuseReason,
		}).Update(); err != nil {
			err = gerror.Wrap(err, "操作失败，请稍后重试！")
			return
		}

		// 订单日志
		if _, err = dao.CarOrderLog.Ctx(ctx).OmitEmptyData().TX(tx).Insert(&entity.CarOrderLog{
			OrderId:     in.Id,
			OrderStatus: "CANCEL",
			ActionWay:   "DISCONFIRMED",
			Remark:      fmt.Sprintf("订单确认拒绝，原因：%s", in.ConfirmRefuseReason),
			OperateType: "ADMIN",
			OperateId:   int(contexts.GetUserId(ctx)),
		}); err != nil {
			return err
		}

		// 确认失败、全额退款
		// 计算退款金额
		var (
			Transaction       []*entity.PmsTransaction
			TransactionRefund []*entity.PmsTransactionRefund
			RefundBalance     float64 // 可退款积分
			RefundFee         float64 // 第三方支付
		)
		if err = dao.PmsTransaction.Ctx(ctx).TX(tx).Where(dao.PmsTransaction.Columns().OrderSn, models.OrderSn).Scan(&Transaction); err != nil {
			return
		}
		if err = dao.PmsTransactionRefund.Ctx(ctx).TX(tx).Where(dao.PmsTransactionRefund.Columns().OrderSn, models.OrderSn).Scan(&TransactionRefund); err != nil {
			return
		}

		for _, v := range Transaction {
			// 可退款金额
			Refundable := v.Amount - v.RefundAmount
			if v.PayType == "BAL" {
				RefundBalance = RefundBalance + Refundable
			} else if v.PayType == "COUPON" {

			} else {
				RefundFee = RefundFee + Refundable
			}
		}
		// 退款金额
		RefundAmount := RefundBalance + RefundFee

		// 修改订单状态
		RefundStatus := "DONE"
		if models.OrderAmount > RefundAmount {
			RefundStatus = "PART"
		}

		if _, err = s.Model(ctx).TX(tx).
			WherePri(in.Id).Data(g.MapStrAny{
			dao.CarOrder.Columns().RefundAmount:       RefundAmount,
			dao.CarOrder.Columns().RefundBalAmount:    RefundBalance,
			dao.CarOrder.Columns().RefundCouponAmount: 0,
			dao.CarOrder.Columns().RefundStatus:       RefundStatus,
			dao.CarOrder.Columns().RefundTime:         gtime.Now(),
			dao.CarOrder.Columns().OrderStatus:        "CANCEL",
			dao.CarOrder.Columns().PayStatus:          "REFUND",
			dao.CarOrder.Columns().CancelTime:         gtime.Now(),
		}).Update(); err != nil {
			err = gerror.Wrap(err, "操作失败，请稍后重试！")
			return
		}

		// 更新服务预定量和预定金额
		if _, err = dao.CarService.Ctx(ctx).TX(tx).Where(dao.CarService.Columns().Id, models.ServiceId).Update(g.MapStrAny{
			dao.CarService.Columns().PayOrderNum:    gdb.Raw("pay_order_num-1"),
			dao.CarService.Columns().PayOrderAmount: gdb.Raw(fmt.Sprintf("pay_order_amount-%f", RefundAmount)),
		}); err != nil {
			err = gerror.Wrap(err, "更新服务信息失败，请稍后重试！")
			return
		}

		// 更新车辆预定量和预定金额
		if models.CarId > 0 {
			if _, err = dao.CarCar.Ctx(ctx).TX(tx).Where(dao.CarCar.Columns().Id, models.CarId).Update(g.MapStrAny{
				dao.CarCar.Columns().PayOrderNum:    gdb.Raw(fmt.Sprintf("pay_order_num-%d", 1)),
				dao.CarCar.Columns().PayOrderAmount: gdb.Raw(fmt.Sprintf("pay_order_amount-%f", RefundAmount)),
			}); err != nil {
				err = gerror.Wrap(err, "更新车辆信息失败，请稍后重试！")
				return
			}
		}

		// 更新司机预定量和预定金额
		if models.DriverId > 0 {
			if _, err = dao.CarDriver.Ctx(ctx).TX(tx).Where(dao.CarDriver.Columns().Id, models.DriverId).Update(g.MapStrAny{
				dao.CarDriver.Columns().PayOrderNum:    gdb.Raw(fmt.Sprintf("pay_order_num-%d", 1)),
				dao.CarDriver.Columns().PayOrderAmount: gdb.Raw(fmt.Sprintf("pay_order_amount-%f", RefundAmount)),
			}); err != nil {
				err = gerror.Wrap(err, "更新司机信息失败，请稍后重试！")
				return
			}
		}

		// 订单日志
		if _, err = dao.CarOrderLog.Ctx(ctx).TX(tx).OmitEmptyData().Insert(&entity.CarOrderLog{
			OrderId:     in.Id,
			OrderStatus: "CANCEL",
			ActionWay:   "REFUND",
			Remark:      "订单已退款",
			OperateType: "SYSTEM",
		}); err != nil {
			return err
		}

		// 全额退款
		err = service.Refund().RefundOrder(ctx, &input_refund.RefundAmountInp{
			OrderSn:      models.OrderSn,
			RefundAmount: RefundAmount,
		}, tx)
		if err != nil {
			err = gerror.Wrap(err, "退款操作失败，请稍后重试！")
			return
		}

		return
	})

}

func (s *sCarOrder) DriverList(ctx context.Context, in *input_car.CarOrderDriverInp) (list []*input_car.CarOrderDriverModel, totalCount int, err error) {
	var (
		OrderInfo        *entity.CarOrder
		WorkingDriverIds []string
		CheckOrderList   []*entity.CarOrder
	)
	if err = dao.CarOrder.Ctx(ctx).Where(dao.CarOrder.Columns().Id, in.Id).Scan(&OrderInfo); err != nil {
		return
	}
	StartTime := gtime.New(OrderInfo.BookStartTime).Timestamp()
	if err = dao.CarOrder.Ctx(ctx).Where(dao.CarOrder.Columns().BookDate, OrderInfo.BookDate).WhereNot(dao.CarOrder.Columns().Id, in.Id).WhereIn(dao.CarOrder.Columns().OrderStatus, g.Slice{"WAIT_SERVE", "SERVING"}).Where(dao.CarOrder.Columns().DispatchStatus, "DONE").Scan(&CheckOrderList); err != nil {
		return
	}
	for _, v := range CheckOrderList {
		OrderStartTime := gtime.New(v.BookStartTime).Timestamp()
		if gtime.New(v.BookEndTime).Timestamp() <= StartTime || OrderStartTime >= gtime.New(OrderInfo.BookEndTime).Timestamp() {

		} else {
			driverIdString := gvar.New(v.DriverId).String()
			WorkingDriverIds = append(WorkingDriverIds, driverIdString)
		}
	}
	WorkingDriverIdsStr := strings.Join(WorkingDriverIds, ",")

	mod := dao.CarDriver.Ctx(ctx)
	mod = mod.Fields(input_car.CarOrderDriverModel{})
	if g.IsEmpty(WorkingDriverIdsStr) {
		WorkingDriverIdsStr = "0"
	}
	mod = mod.Fields(fmt.Sprintf(`
	CASE
        WHEN work_status='REST' THEN 1
        WHEN id IN(%s) THEN 2
        ELSE 3
    END AS work_status_enum
`, WorkingDriverIdsStr))
	mod = mod.Where(dao.CarDriver.Columns().Status, 1)
	mod = mod.OrderDesc(fmt.Sprintf(`
	CASE
        WHEN work_status='REST' THEN 1
        WHEN id IN(%s) THEN 2
        ELSE 3
    END
`, WorkingDriverIdsStr))
	mod = mod.Page(in.Page, in.PerPage)
	if err = mod.ScanAndCount(&list, &totalCount, false); err != nil {
		err = gerror.Wrap(err, "获取司机列表失败，请稍后重试！")
		return
	}
	return
}

func (s *sCarOrder) Dispatch(ctx context.Context, in *input_car.CarOrderDispatchInp) (err error) {

	var (
		models         *entity.CarOrder
		DriverInfo     *entity.CarDriver
		CheckOrderList []*entity.CarOrder
		CantOrderNum   int
		actionWay      string
		logDesc        string
	)
	if err = s.Model(ctx).Where("id", in.Id).Scan(&models); err != nil {
		err = gerror.Wrap(err, consts.ErrorORM)
		return
	}

	if models == nil {
		err = gerror.New("订单信息不存在或已被删除")
		return
	}

	if models.OrderStatus != "WAIT_SERVE" || models.DispatchStatus != "WAIT" {
		err = gerror.New("订单状态不正确")
		return
	}

	if err = dao.CarDriver.Ctx(ctx).WherePri(in.DriverId).Scan(&DriverInfo); err != nil {
		return
	}

	// 重新判断下司机

	if err = dao.CarOrder.Ctx(ctx).Where(dao.CarOrder.Columns().BookDate, models.BookDate).Where(dao.CarOrder.Columns().DriverId, in.DriverId).WhereNot(dao.CarOrder.Columns().Id, in.Id).WhereIn(dao.CarOrder.Columns().OrderStatus, g.Slice{"WAIT_SERVE", "SERVING"}).Scan(&CheckOrderList); err != nil {
		return
	}
	for _, v := range CheckOrderList {
		OrderStartTime := gtime.New(v.BookStartTime).Timestamp()
		if gtime.New(v.BookEndTime).Timestamp() <= gtime.New(models.BookStartTime).Timestamp() || OrderStartTime >= gtime.New(models.BookEndTime).Timestamp() {

		} else {
			CantOrderNum++
		}
	}

	if CantOrderNum > 0 {
		err = gerror.New("司机不可派单，请重新选择")
		return
	}

	if models.IsReturn == 1 {
		actionWay = "RE_DISPATCH"
		logDesc = "新司机已接单"
	} else {
		actionWay = "DISPATCH"
		logDesc = "预约成功，司机已接单"
	}

	return g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) (err error) {
		if _, err = s.Model(ctx).
			WherePri(in.Id).Data(input_car.CarOrderDispatchInp{
			IsReturn:           2,
			DispatchStatus:     "DONE",
			DispatchTime:       gtime.Now(),
			DispatchOperatorId: in.DispatchOperatorId,
			DispatchDesc:       in.DispatchDesc,
			DriverId:           in.DriverId,
			CarId:              DriverInfo.CarId,
		}).OmitEmptyData().Update(); err != nil {
			err = gerror.Wrap(err, "操作失败，请稍后重试！")
			return
		}

		// 订单日志
		if _, err = dao.CarOrderLog.Ctx(ctx).OmitEmptyData().Insert(&entity.CarOrderLog{
			OrderId:     in.Id,
			OrderStatus: "WAIT_SERVE",
			ActionWay:   actionWay,
			Remark:      logDesc,
			OperateType: "ADMIN",
			OperateId:   int(contexts.GetUserId(ctx)),
		}); err != nil {
			return err
		}

		// 打印
		_ = service.BasicsPrinter().PrinterCarOrder(ctx, &input_basics.PrinterCarOrderInp{
			OrderId: in.Id,
		})

		// 更新司机统计
		if _, err = dao.CarDriver.Ctx(ctx).Where(dao.CarDriver.Columns().Id, in.DriverId).Update(g.MapStrAny{
			dao.CarDriver.Columns().TotalOrderNum:    gdb.Raw("total_order_num+1"),
			dao.CarDriver.Columns().TotalOrderAmount: gdb.Raw(fmt.Sprintf("total_order_amount+%f", models.OrderAmount)),
			dao.CarDriver.Columns().PayOrderNum:      gdb.Raw("pay_order_num+1"),
			dao.CarDriver.Columns().PayOrderAmount:   gdb.Raw(fmt.Sprintf("pay_order_amount+%f", models.OrderAmount)),
		}); err != nil {
			err = gerror.Wrap(err, "更新服务信息失败，请稍后重试！")
			return
		}

		// 写入结算
		var (
			CarSettlement   *entity.CarSettlement
			SettlementRate  float64
			SettlementType  int
			SettlementCycle int
		)
		if err = dao.CarSettlement.Ctx(ctx).WherePri(DriverInfo.SettlementId).Scan(&CarSettlement); err != nil {
			return
		}
		if DriverInfo.SettlementType == 1 {
			// 跟随系统
			if !g.IsEmpty(CarSettlement) {
				SettlementRate = CarSettlement.Rate
			} else {
				SettlementRate = 0
			}
		} else {
			// 自定义
			SettlementRate = DriverInfo.SettlementRate
		}
		if !g.IsEmpty(CarSettlement) {
			SettlementType = CarSettlement.Type
			SettlementCycle = CarSettlement.Cycle
		} else {
			SettlementType = 1
			SettlementCycle = 1
		}
		if _, err = s.Model(ctx).
			WherePri(in.Id).Data(input_car.CarOrderSettlementInp{
			SettlementRate:  SettlementRate,
			SettlementType:  SettlementType,
			SettlementCycle: SettlementCycle,
		}).OmitEmptyData().Update(); err != nil {
			err = gerror.Wrap(err, "操作失败，请稍后重试！")
			return
		}

		return
	})

}

// SettleOrderList 结算订单列表
func (s *sCarOrder) SettleOrderList(ctx context.Context, in *input_car.SettleCarOrderListInp) (list []*input_car.SettleCarOrderListModel, totalCount int, err error) {
	mod := s.Model(ctx).WithAll()

	mod = mod.Fields(input_car.SettleCarOrderListModel{})

	if !g.IsEmpty(in.SettlementOrderId) {
		mod = mod.Where(dao.CarOrder.Columns().SettlementOrderId, in.SettlementOrderId)
	}

	if !g.IsEmpty(in.OrderSn) {
		mod = mod.WhereLike(dao.CarOrder.Columns().OrderSn, "%"+in.OrderSn+"%")
	}

	if len(in.CreatedAt) == 2 {
		mod = mod.WhereBetween(dao.CarOrder.Columns().CreatedAt, in.CreatedAt[0], in.CreatedAt[1])
	}

	mod = mod.Page(in.Page, in.PerPage)

	mod = mod.OrderDesc(dao.CarOrder.Columns().Id)
	//mod = mod.Hook(hook2.PmsFindLanguageValueHook)

	if err = mod.ScanAndCount(&list, &totalCount, false); err != nil {
		err = gerror.Wrap(err, "获取结算订单列表失败，请稍后重试！")
		return
	}
	return
}

// Refund 订单退款
func (s *sCarOrder) Refund(ctx context.Context, in *input_car.CarOrderRefundInp) (err error) {

	var models *entity.CarOrder
	if err = s.Model(ctx).Where("id", in.Id).Scan(&models); err != nil {
		err = gerror.Wrap(err, consts.ErrorORM)
		return
	}

	if models == nil {
		err = gerror.New("订单信息不存在或已被删除")
		return
	}

	if models.PayStatus != "HAVE_PAID" {
		err = gerror.New("订单支付状态不正确")
		return
	}

	if models.OrderStatus == "SERVING" || models.OrderStatus == "DONE" {
		err = gerror.New("订单状态不正确")
		return
	}

	return g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) (err error) {
		// 计算退款金额
		var (
			Transaction       []*entity.PmsTransaction
			TransactionRefund []*entity.PmsTransactionRefund
			CancelFee         float64 // 退款手续费
			RefundBalance     float64 // 可退款积分
			RefundFee         float64 // 第三方支付
		)
		CancelFee = models.OrderAmount - models.CouponAmount - in.RefundMoney
		CancelFeeCalc := CancelFee
		if err = dao.PmsTransaction.Ctx(ctx).TX(tx).Where(dao.PmsTransaction.Columns().OrderSn, models.OrderSn).Scan(&Transaction); err != nil {
			return
		}
		if err = dao.PmsTransactionRefund.Ctx(ctx).TX(tx).Where(dao.PmsTransactionRefund.Columns().OrderSn, models.OrderSn).Scan(&TransactionRefund); err != nil {
			return
		}

		for _, v := range Transaction {
			// 可退款金额
			Refundable := v.Amount - v.RefundAmount
			if v.PayType == "BAL" {
				if g.IsEmpty(CancelFeeCalc) {
					RefundBalance += Refundable
				} else if CancelFeeCalc > Refundable {
					RefundBalance += 0
					CancelFeeCalc = CancelFeeCalc - Refundable
				} else {
					RefundBalance += Refundable - CancelFeeCalc
					CancelFeeCalc = 0
				}
			} else if v.PayType == "COUPON" {

			} else {
				if g.IsEmpty(CancelFeeCalc) {
					RefundFee += Refundable
				} else if CancelFeeCalc > Refundable {
					RefundFee += 0
					CancelFeeCalc = CancelFeeCalc - Refundable
				} else {
					RefundFee += Refundable - CancelFeeCalc
					CancelFeeCalc = 0
				}
			}
		}
		// 退款金额
		RefundAmount := RefundBalance + RefundFee

		OrderTotalRefundAmount := RefundAmount + models.RefundAmount
		OrderTotalRefundBalance := RefundBalance + models.RefundBalAmount

		AdminOrderTotalRefundAmount := RefundAmount + models.AdminRefundAmount
		AdminOrderTotalRefundBalance := RefundBalance + models.AdminRefundBalAmount

		// 修改订单状态
		RefundStatus := "DONE"
		if models.OrderAmount > OrderTotalRefundAmount {
			RefundStatus = "PART"
		}
		if in.RefundType == 1 {
			if _, err = s.Model(ctx).TX(tx).
				WherePri(in.Id).Data(g.MapStrAny{
				dao.CarOrder.Columns().RefundAmount:         OrderTotalRefundAmount,
				dao.CarOrder.Columns().RefundBalAmount:      OrderTotalRefundBalance,
				dao.CarOrder.Columns().AdminRefundAmount:    AdminOrderTotalRefundAmount,
				dao.CarOrder.Columns().AdminRefundBalAmount: AdminOrderTotalRefundBalance,
				dao.CarOrder.Columns().RefundCouponAmount:   0,
				dao.CarOrder.Columns().RefundStatus:         RefundStatus,
				dao.CarOrder.Columns().RefundTime:           gtime.Now(),
				dao.CarOrder.Columns().AdminCancelReason:    in.AdminCancelReason,
			}).Update(); err != nil {
				err = gerror.Wrap(err, "操作失败，请稍后重试！")
				return
			}
			// 更新服务预定量和预定金额
			if _, err = dao.CarService.Ctx(ctx).TX(tx).Where(dao.CarService.Columns().Id, models.ServiceId).Update(g.MapStrAny{
				dao.CarService.Columns().PayOrderAmount: gdb.Raw(fmt.Sprintf("pay_order_amount-%f", RefundAmount)),
			}); err != nil {
				err = gerror.Wrap(err, "更新服务信息失败，请稍后重试！")
				return
			}

			// 更新车辆预定量和预定金额
			if models.CarId > 0 {
				if _, err = dao.CarCar.Ctx(ctx).TX(tx).Where(dao.CarCar.Columns().Id, models.CarId).Update(g.MapStrAny{
					dao.CarCar.Columns().PayOrderAmount: gdb.Raw(fmt.Sprintf("pay_order_amount-%f", RefundAmount)),
				}); err != nil {
					err = gerror.Wrap(err, "更新车辆信息失败，请稍后重试！")
					return
				}
			}

			// 更新司机预定量和预定金额
			if models.DriverId > 0 {
				if _, err = dao.CarDriver.Ctx(ctx).TX(tx).Where(dao.CarDriver.Columns().Id, models.DriverId).Update(g.MapStrAny{
					dao.CarDriver.Columns().PayOrderAmount: gdb.Raw(fmt.Sprintf("pay_order_amount-%f", RefundAmount)),
				}); err != nil {
					err = gerror.Wrap(err, "更新司机信息失败，请稍后重试！")
					return
				}
			}
		} else {
			// 退款并取消
			if _, err = s.Model(ctx).TX(tx).
				WherePri(in.Id).Data(g.MapStrAny{
				dao.CarOrder.Columns().RefundAmount:         OrderTotalRefundAmount,
				dao.CarOrder.Columns().RefundBalAmount:      OrderTotalRefundBalance,
				dao.CarOrder.Columns().AdminRefundAmount:    AdminOrderTotalRefundAmount,
				dao.CarOrder.Columns().AdminRefundBalAmount: AdminOrderTotalRefundBalance,
				dao.CarOrder.Columns().RefundCouponAmount:   0,
				dao.CarOrder.Columns().RefundStatus:         RefundStatus,
				dao.CarOrder.Columns().RefundTime:           gtime.Now(),
				dao.CarOrder.Columns().AdminCancelReason:    in.AdminCancelReason,
				dao.CarOrder.Columns().OrderStatus:          "CANCEL",
				dao.CarOrder.Columns().PayStatus:            "REFUND",
				dao.CarOrder.Columns().CancelTime:           gtime.Now(),
			}).Update(); err != nil {
				err = gerror.Wrap(err, "操作失败，请稍后重试！")
				return
			}
			// 更新服务预定量和预定金额
			if _, err = dao.CarService.Ctx(ctx).TX(tx).Where(dao.CarService.Columns().Id, models.ServiceId).Update(g.MapStrAny{
				dao.CarService.Columns().PayOrderNum:    gdb.Raw("pay_order_num-1"),
				dao.CarService.Columns().PayOrderAmount: gdb.Raw(fmt.Sprintf("pay_order_amount-%f", RefundAmount)),
			}); err != nil {
				err = gerror.Wrap(err, "更新服务信息失败，请稍后重试！")
				return
			}

			// 更新车辆预定量和预定金额
			if models.CarId > 0 {
				if _, err = dao.CarCar.Ctx(ctx).TX(tx).Where(dao.CarCar.Columns().Id, models.CarId).Update(g.MapStrAny{
					dao.CarCar.Columns().PayOrderNum:    gdb.Raw(fmt.Sprintf("pay_order_num-%d", 1)),
					dao.CarCar.Columns().PayOrderAmount: gdb.Raw(fmt.Sprintf("pay_order_amount-%f", RefundAmount)),
				}); err != nil {
					err = gerror.Wrap(err, "更新车辆信息失败，请稍后重试！")
					return
				}
			}

			// 更新司机预定量和预定金额
			if models.DriverId > 0 {
				if _, err = dao.CarDriver.Ctx(ctx).TX(tx).Where(dao.CarDriver.Columns().Id, models.DriverId).Update(g.MapStrAny{
					dao.CarDriver.Columns().PayOrderNum:    gdb.Raw(fmt.Sprintf("pay_order_num-%d", 1)),
					dao.CarDriver.Columns().PayOrderAmount: gdb.Raw(fmt.Sprintf("pay_order_amount-%f", RefundAmount)),
				}); err != nil {
					err = gerror.Wrap(err, "更新司机信息失败，请稍后重试！")
					return
				}
			}
		}
		if _, err = dao.CarOrder.Ctx(ctx).TX(tx).WherePri(in.Id).Update(g.MapStrAny{
			dao.CarOrder.Columns().AdminCancelNum: gdb.Raw("admin_cancel_num+1"),
		}); err != nil {
			err = gerror.Wrap(err, "更新失败，请稍后重试！")
			return
		}

		if RefundAmount > 0 {
			// 退款
			err = service.Refund().RefundOrder(ctx, &input_refund.RefundAmountInp{
				OrderSn:      models.OrderSn,
				RefundAmount: RefundAmount,
			}, tx)
			if err != nil {
				err = gerror.Wrap(err, "退款操作失败，请稍后重试！")
				return
			}
		}

		// 订单日志
		if _, err = dao.CarOrderLog.Ctx(ctx).TX(tx).OmitEmptyData().Insert(&entity.CarOrderLog{
			OrderId:     int(in.Id),
			OrderStatus: models.OrderStatus,
			ActionWay:   "ADMIN_REFUND",
			Remark:      fmt.Sprintf("后台退款，原因：%s", in.AdminCancelReason),
			OperateType: "ADMIN",
			OperateId:   int(contexts.GetUserId(ctx)),
		}); err != nil {
			return err
		}

		if in.RefundType == 2 {
			// 订单日志
			if _, err = dao.CarOrderLog.Ctx(ctx).TX(tx).OmitEmptyData().Insert(&entity.CarOrderLog{
				OrderId:     int(in.Id),
				OrderStatus: "CANCEL",
				ActionWay:   "CANCEL",
				Remark:      "后台订单取消",
				OperateType: "ADMIN",
				OperateId:   int(contexts.GetUserId(ctx)),
			}); err != nil {
				return err
			}

			if models.OrderType == "INNN" && !g.IsEmpty(models.InnnOrderId) {
				if _, err = aladdinApi.NewClient(ctx).CancelOrder(ctx, &aladdinApi.CancelOrderParams{OrderId: models.InnnOrderId}); err != nil {
					return
				}
			}
		}

		return
	})

}

func (s *sCarOrder) GoOut(ctx context.Context, in *input_car.CarOrderGoOutInp) (err error) {

	var models *entity.CarOrder
	if err = s.Model(ctx).Where("id", in.Id).Scan(&models); err != nil {
		err = gerror.Wrap(err, consts.ErrorORM)
		return
	}

	if models == nil {
		err = gerror.New("订单信息不存在或已被删除")
		return
	}

	if models.OrderStatus != "WAIT_SERVE" {
		err = gerror.New("订单状态不正确")
		return
	}

	if models.DispatchStatus != "DONE" {
		err = gerror.New("调度状态不正确")
		return
	}

	if !g.IsEmpty(models.DriverGoTime) {
		err = gerror.New("司机已出发，请勿重复点击")
		return
	}

	return g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) (err error) {
		if _, err = s.Model(ctx).
			WherePri(in.Id).Data(input_car.CarOrderGoOutFields{
			DriverGoTime: gtime.Now(),
		}).Update(); err != nil {
			err = gerror.Wrap(err, "操作失败，请稍后重试！")
			return
		}

		// 订单日志
		if _, err = dao.CarOrderLog.Ctx(ctx).OmitEmptyData().Insert(&entity.CarOrderLog{
			OrderId:     in.Id,
			OrderStatus: "SERVING",
			ActionWay:   "OUT",
			Remark:      "司机已出发",
			OperateType: "ADMIN",
			OperateId:   int(contexts.GetUserId(ctx)),
		}); err != nil {
			return err
		}

		// 司机状态改为工作中
		if _, err = dao.CarDriver.Ctx(ctx).
			WherePri(models.DriverId).
			Data(g.MapStrAny{
				dao.CarDriver.Columns().WorkStatus: "WORKING",
			}).Update(); err != nil {
			err = gerror.Wrap(err, "修改司机工作状态失败，请稍后重试！")
			return
		}

		// 车辆状态改为工作中
		if models.CarId > 0 {
			if _, err = dao.CarCar.Ctx(ctx).
				WherePri(models.CarId).
				Data(g.MapStrAny{
					dao.CarCar.Columns().WorkStatus: "WORKING",
				}).Update(); err != nil {
				err = gerror.Wrap(err, "修改车辆工作状态失败，请稍后重试！")
				return
			}
		}

		return
	})

}

func (s *sCarOrder) StartService(ctx context.Context, in *input_car.CarOrderStartServiceInp) (err error) {

	var models *entity.CarOrder
	if err = s.Model(ctx).Where("id", in.Id).Scan(&models); err != nil {
		err = gerror.Wrap(err, consts.ErrorORM)
		return
	}

	if models == nil {
		err = gerror.New("订单信息不存在或已被删除")
		return
	}

	if models.OrderStatus != "WAIT_SERVE" {
		err = gerror.New("订单状态不正确")
		return
	}

	if models.DispatchStatus != "DONE" {
		err = gerror.New("调度状态不正确")
		return
	}

	return g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) (err error) {
		if _, err = s.Model(ctx).
			WherePri(in.Id).Data(input_car.CarOrderStartServiceFields{
			OrderStatus:     "SERVING",
			ActualStartTime: gtime.Now(),
		}).Update(); err != nil {
			err = gerror.Wrap(err, "操作失败，请稍后重试！")
			return
		}

		// 订单日志
		if _, err = dao.CarOrderLog.Ctx(ctx).OmitEmptyData().Insert(&entity.CarOrderLog{
			OrderId:     in.Id,
			OrderStatus: "SERVING",
			ActionWay:   "SERVING",
			Remark:      "司机已到达出发地",
			OperateType: "ADMIN",
			OperateId:   int(contexts.GetUserId(ctx)),
		}); err != nil {
			return err
		}

		//// 司机状态改为工作中
		//if _, err = dao.CarDriver.Ctx(ctx).
		//	WherePri(models.DriverId).
		//	Data(g.MapStrAny{
		//		dao.CarDriver.Columns().WorkStatus: "WORKING",
		//	}).Update(); err != nil {
		//	err = gerror.Wrap(err, "修改司机工作状态失败，请稍后重试！")
		//	return
		//}
		//
		//// 车辆状态改为工作中
		//if models.CarId > 0 {
		//	if _, err = dao.CarCar.Ctx(ctx).
		//		WherePri(models.CarId).
		//		Data(g.MapStrAny{
		//			dao.CarCar.Columns().WorkStatus: "WORKING",
		//		}).Update(); err != nil {
		//		err = gerror.Wrap(err, "修改车辆工作状态失败，请稍后重试！")
		//		return
		//	}
		//}

		return
	})

}

func (s *sCarOrder) EndService(ctx context.Context, in *input_car.CarOrderEndServiceInp) (err error) {

	var (
		models         *entity.CarOrder
		DriverInfo     *entity.CarDriver
		SettlementInfo *entity.CarSettlement
	)
	if err = s.Model(ctx).Where("id", in.Id).Scan(&models); err != nil {
		err = gerror.Wrap(err, consts.ErrorORM)
		return
	}

	if models == nil {
		err = gerror.New("订单信息不存在或已被删除")
		return
	}

	if models.OrderStatus != "SERVING" {
		err = gerror.New("订单状态不正确")
		return
	}

	return g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) (err error) {
		if _, err = s.Model(ctx).
			WherePri(in.Id).Data(input_car.CarOrderEndServiceFields{
			OrderStatus:   "DONE",
			ActualEndTime: gtime.Now(),
		}).Update(); err != nil {
			err = gerror.Wrap(err, "操作失败，请稍后重试！")
			return
		}

		// 订单日志
		if _, err = dao.CarOrderLog.Ctx(ctx).OmitEmptyData().Insert(&entity.CarOrderLog{
			OrderId:     in.Id,
			OrderStatus: "DONE",
			ActionWay:   "DONE",
			Remark:      "成功到达目的地",
			OperateType: "ADMIN",
			OperateId:   int(contexts.GetUserId(ctx)),
		}); err != nil {
			return err
		}

		// 司机状态改为可约
		if _, err = dao.CarDriver.Ctx(ctx).
			WherePri(models.DriverId).
			Data(g.MapStrAny{
				dao.CarDriver.Columns().WorkStatus: "CANORDER",
			}).Update(); err != nil {
			err = gerror.Wrap(err, "修改司机工作状态失败，请稍后重试！")
			return
		}

		// 车辆状态改为可约
		if models.CarId > 0 {
			if _, err = dao.CarCar.Ctx(ctx).
				WherePri(models.CarId).
				Data(g.MapStrAny{
					dao.CarCar.Columns().WorkStatus: "CANORDER",
				}).Update(); err != nil {
				err = gerror.Wrap(err, "修改车辆工作状态失败，请稍后重试！")
				return
			}
		}

		// 记录分佣
		_ = dao.CarDriver.Ctx(ctx).WherePri(models.DriverId).Scan(&DriverInfo)
		_ = dao.CarSettlement.Ctx(ctx).WherePri(DriverInfo.SettlementId).Scan(&SettlementInfo)
		cost := SettlementInfo.Cost
		settlementAmount := models.OrderAmount
		if !g.IsEmpty(cost) {
			costArr := strings.Split(cost, ",")
			constIsCoupon := false
			constIsBal := false
			for _, costItem := range costArr {
				if gvar.New(costItem).Int() == 1 {
					constIsCoupon = true
				}
				if gvar.New(costItem).Int() == 2 {
					constIsBal = true
				}
			}
			if !constIsCoupon {
				settlementAmount = settlementAmount - models.CouponAmount
			}
			if !constIsBal {
				settlementAmount = settlementAmount - models.BalAmount
			}
		}
		settlementAmount = decimal.NewFromFloat(settlementAmount).Mul(decimal.NewFromFloat(models.SettlementRate)).Div(decimal.NewFromFloat(100)).Round(0).InexactFloat64()
		if _, err = dao.CarOrder.Ctx(ctx).TX(tx).Data(g.Map{
			dao.CarOrder.Columns().SettlementAmount: settlementAmount,
		}).WherePri(in.Id).Update(); err != nil {
			return
		}

		// 转发到返利队列
		_ = rabbitmq.SendMqMessage(ctx, &rabbitmq.SendMqMessageParams{
			ExchangeName: consts.RabbitMQExchangeName,
			QueueName:    consts.RabbitMQQueueNameRebate,
			DataByte:     gvar.New(models.OrderSn).Bytes(),
			Header:       nil,
		})
		_ = rabbitmq.SendMqMessage(ctx, &rabbitmq.SendMqMessageParams{
			ExchangeName: consts.RabbitMQExchangeName,
			QueueName:    consts.RabbitMQQueueNameExp,
			DataByte:     gvar.New(models.OrderSn).Bytes(),
			Header:       nil,
		})

		return
	})

}
